

    ' ---------------------------------------------------------------------------- 
    '   DETERMINANT - DOUBLE ARRAYS - THE BEST
    '   Execution time with 25 rows: 170 uS (PC) to 220 uS (notebook)
    ' ----------------------------------------------------------------------------
    Public Function Determinant(ByVal Mat(,) As Double) As Double
        Dim sw As Stopwatch = New Stopwatch
        sw.Start()

        Dim Rows As Int32 = Mat.GetUpperBound(0)
        Dim Cols As Int32 = Mat.GetUpperBound(1)
        If Rows <> Cols Then
            Throw New Exception("Matrix should be a square matrix.")
        End If

        Dim k, k1, i, j As Int32
        Dim save As Double
        Dim ArrayK As Double
        Dim Det As Double = 1
        Dim DArray(,) As Double = CType(Mat.Clone(), Double(,))

        For k = 0 To Rows
            If DArray(k, k) = 0 Then
                j = k
                Do While ((j < Rows) And (DArray(k, j) = 0))
                    j = j + 1
                Loop
                If DArray(k, j) = 0 Then
                    Det = 0
                    Exit Function
                Else
                    For i = k To Rows
                        save = DArray(i, j)
                        DArray(i, j) = DArray(i, k)
                        DArray(i, k) = save
                    Next i
                End If
                Det = -Det
            End If
            ArrayK = DArray(k, k)
            Det = Det * ArrayK
            If k < Rows Then
                k1 = k + 1
                For i = k1 To Rows
                    For j = k1 To Rows
                        DArray(i, j) = DArray(i, j) - DArray(i, k) * (DArray(k, j) / ArrayK)
                    Next j
                Next i
            End If
        Next
        Form_Main.Text = (sw.Elapsed.TotalMilliseconds * 1000).ToString("0.0")
        Return Det
    End Function





    ' -------------------------------------------------------------------------------------- 
    '   DETERMINANT - TYPE 4 - WITH LU DECOMPOSITION
    '   Execution time with 25 rows: 400 uS (PC) to 600 uS (notebook)
    ' --------------------------------------------------------------------------------------
    Public Function Determinant4(ByVal sourceMatrix(,) As Single) As Single
        Dim sw As Stopwatch = New Stopwatch
        sw.Start()

        ' ----- Calculate the determinant of a matrix.
        Dim result As Single
        Dim pivots As Integer
        Dim count As Integer

        ' ----- Only calculate the determinants of square matrices.
        If (UBound(sourceMatrix, 1) <> UBound(sourceMatrix, 2)) Then
            Throw New Exception( _
                "Determinant only calculated for square matrices.")
        End If
        Dim rank As Integer = UBound(sourceMatrix, 1)

        ' ----- Make a copy of the matrix so we can work inside of it.
        Dim workMatrix(rank, rank) As Single
        Array.Copy(sourceMatrix, workMatrix, sourceMatrix.Length)

        ' ----- Use LU decomposition to form a triangular matrix.
        Dim rowPivots(rank) As Integer
        Dim colPivots(rank) As Integer
        workMatrix = FormLU(workMatrix, rowPivots, colPivots, count)

        ' ----- Get the product at each of the pivot points.
        result = 1
        For pivots = 0 To rank
            result *= workMatrix(rowPivots(pivots), colPivots(pivots))
        Next pivots

        ' ----- Determine the sign of the result using LaPlace's formula.
        result = CSng(-1.0 ^ count) * result

        Form_Main.Text = (sw.Elapsed.TotalMilliseconds * 1000).ToString("0.0")
        Return result
    End Function

    Private Function FormLU(ByVal sourceMatrix(,) As Single, _
            ByRef rowPivots() As Integer, ByRef colPivots() As Integer, _
            ByRef rowsAndCols As Integer) As Single(,)
        ' ----- Perform an LU (lower and upper) decomposition of a matrix,
        '       a modified form of Gaussian elimination.
        Dim eachRow As Integer
        Dim eachCol As Integer
        Dim pivot As Integer
        Dim rowIndex As Integer
        Dim colIndex As Integer
        Dim bestRow As Integer
        Dim bestCol As Integer
        Dim rowToPivot As Integer
        Dim colToPivot As Integer
        Dim maxValue As Double
        Dim testValue As Double
        Dim oldMax As Double
        Const Deps As Double = 0.0000000000000001

        ' ----- Determine the size of the array.
        Dim rank As Integer = UBound(sourceMatrix, 1)
        Dim destMatrix(rank, rank) As Single
        Dim rowNorm(rank) As Single
        ReDim rowPivots(rank)
        ReDim colPivots(rank)

        ' ----- Make a copy of the array so we don't mess it up.
        Array.Copy(sourceMatrix, destMatrix, sourceMatrix.Length)

        ' ----- Initialize row and column pivot arrays.
        For eachRow = 0 To rank
            rowPivots(eachRow) = eachRow
            colPivots(eachRow) = eachRow
            For eachCol = 0 To rank
                rowNorm(eachRow) += Math.Abs(destMatrix(eachRow, eachCol))
            Next eachCol
            If (rowNorm(eachRow) = 0) Then
                Throw New Exception("Cannot invert a singular matrix.")
            End If
        Next eachRow

        ' ----- Use Gauss-Jordan elimination on the matrix rows.
        For pivot = 0 To rank - 1
            maxValue = 0
            For eachRow = pivot To rank
                rowIndex = rowPivots(eachRow)
                For eachCol = pivot To rank
                    colIndex = colPivots(eachCol)
                    testValue = Math.Abs(destMatrix(rowIndex, colIndex)) _
                        / rowNorm(rowIndex)
                    If (testValue > maxValue) Then
                        maxValue = testValue
                        bestRow = eachRow
                        bestCol = eachCol
                    End If
                Next eachCol
            Next eachRow

            ' ----- Detect a singular, or very nearly singular, matrix.
            If (maxValue = 0) Then
                Throw New Exception("Singular matrix used for LU.")
            ElseIf (pivot > 1) Then
                If (maxValue < (Deps * oldMax)) Then
                    Throw New Exception("Non-invertible matrix used for LU.")
                End If
            End If
            oldMax = maxValue

            ' ----- Swap row pivot values for the best row.
            If (rowPivots(pivot) <> rowPivots(bestRow)) Then
                rowsAndCols += 1
                Swap(rowPivots(pivot), rowPivots(bestRow))
            End If

            ' ----- Swap column pivot values for the best column.
            If (colPivots(pivot) <> colPivots(bestCol)) Then
                rowsAndCols += 1
                Swap(colPivots(pivot), colPivots(bestCol))
            End If

            ' ----- Work with the current pivot points.
            rowToPivot = rowPivots(pivot)
            colToPivot = colPivots(pivot)

            ' ----- Modify the remaining rows from the pivot points.
            For eachRow = (pivot + 1) To rank
                rowIndex = rowPivots(eachRow)
                destMatrix(rowIndex, colToPivot) = _
                    -destMatrix(rowIndex, colToPivot) / _
                    destMatrix(rowToPivot, colToPivot)
                For eachCol = (pivot + 1) To rank
                    colIndex = colPivots(eachCol)
                    destMatrix(rowIndex, colIndex) += _
                        destMatrix(rowIndex, colToPivot) * _
                        destMatrix(rowToPivot, colIndex)
                Next eachCol
            Next eachRow
        Next pivot

        ' ----- Detect a non-invertible matrix.
        If (destMatrix(rowPivots(rank), colPivots(rank)) = 0) Then
            Throw New Exception("Non-invertible matrix used for LU.")
        ElseIf (Math.Abs(destMatrix(rowPivots(rank), colPivots(rank))) / _
                rowNorm(rowPivots(rank))) < (Deps * oldMax) Then
            Throw New Exception("Non-invertible matrix used for LU.")
        End If

        ' ----- Success. Return the LU triangular matrix.
        Return destMatrix
    End Function

    Private Sub Swap(ByRef firstValue As Integer, ByRef secondValue As Integer)
        Dim holdValue As Integer
        holdValue = firstValue
        firstValue = secondValue
        secondValue = holdValue
    End Sub




    ' ---------------------------------------------------------------------------- 
    '   DETERMINANT - TYPE 4 - DOUBLE ARRAYS
    '   Execution time with 25 rows: 380 uS (PC) to 400 uS (notebook)
    ' ----------------------------------------------------------------------------
    Public Function Determinant4_Double(ByVal sourceMatrix(,) As Double) As Single
        Dim sw As Stopwatch = New Stopwatch
        sw.Start()

        ' ----- Calculate the determinant of a matrix.
        Dim result As Double
        Dim pivots As Integer
        Dim count As Integer

        ' ----- Only calculate the determinants of square matrices.
        If (UBound(sourceMatrix, 1) <> UBound(sourceMatrix, 2)) Then
            Throw New Exception( _
                "Determinant only calculated for square matrices.")
        End If
        Dim rank As Integer = UBound(sourceMatrix, 1)

        ' ----- Make a copy of the matrix so we can work inside of it.
        Dim workMatrix(rank, rank) As Double
        Array.Copy(sourceMatrix, workMatrix, sourceMatrix.Length)

        ' ----- Use LU decomposition to form a triangular matrix.
        Dim rowPivots(rank) As Integer
        Dim colPivots(rank) As Integer
        workMatrix = FormLU_Double(workMatrix, rowPivots, colPivots, count)

        ' ----- Get the product at each of the pivot points.
        result = 1
        For pivots = 0 To rank
            result *= workMatrix(rowPivots(pivots), colPivots(pivots))
        Next pivots

        ' ----- Determine the sign of the result using LaPlace's formula.
        result = (-1.0 ^ count) * result

        Form_Main.Text = (sw.Elapsed.TotalMilliseconds * 1000).ToString("0.0")
        Return CSng(result)
    End Function

    Private Function FormLU_Double(ByVal sourceMatrix(,) As Double, _
                                    ByRef rowPivots() As Integer, _
                                    ByRef colPivots() As Integer, _
                                    ByRef rowsAndCols As Integer) As Double(,)
        ' ----- Perform an LU (lower and upper) decomposition of a matrix,
        '       a modified form of Gaussian elimination.
        Dim eachRow As Integer
        Dim eachCol As Integer
        Dim pivot As Integer
        Dim rowIndex As Integer
        Dim colIndex As Integer
        Dim bestRow As Integer
        Dim bestCol As Integer
        Dim rowToPivot As Integer
        Dim colToPivot As Integer
        Dim maxValue As Double
        Dim testValue As Double
        Dim oldMax As Double
        Const Deps As Double = 0.0000000000000001

        ' ----- Determine the size of the array.
        Dim rank As Integer = UBound(sourceMatrix, 1)
        Dim destMatrix(rank, rank) As Double
        Dim rowNorm(rank) As Double
        ReDim rowPivots(rank)
        ReDim colPivots(rank)

        ' ----- Make a copy of the array so we don't mess it up.
        Array.Copy(sourceMatrix, destMatrix, sourceMatrix.Length)

        ' ----- Initialize row and column pivot arrays.
        For eachRow = 0 To rank
            rowPivots(eachRow) = eachRow
            colPivots(eachRow) = eachRow
            For eachCol = 0 To rank
                rowNorm(eachRow) += Math.Abs(destMatrix(eachRow, eachCol))
            Next eachCol
            If (rowNorm(eachRow) = 0) Then
                Throw New Exception("Cannot invert a singular matrix.")
            End If
        Next eachRow

        ' ----- Use Gauss-Jordan elimination on the matrix rows.
        For pivot = 0 To rank - 1
            maxValue = 0
            For eachRow = pivot To rank
                rowIndex = rowPivots(eachRow)
                For eachCol = pivot To rank
                    colIndex = colPivots(eachCol)
                    testValue = Math.Abs(destMatrix(rowIndex, colIndex)) _
                        / rowNorm(rowIndex)
                    If (testValue > maxValue) Then
                        maxValue = testValue
                        bestRow = eachRow
                        bestCol = eachCol
                    End If
                Next eachCol
            Next eachRow

            ' ----- Detect a singular, or very nearly singular, matrix.
            If (maxValue = 0) Then
                Throw New Exception("Singular matrix used for LU.")
            ElseIf (pivot > 1) Then
                If (maxValue < (Deps * oldMax)) Then
                    Throw New Exception("Non-invertible matrix used for LU.")
                End If
            End If
            oldMax = maxValue

            ' ----- Swap row pivot values for the best row.
            If (rowPivots(pivot) <> rowPivots(bestRow)) Then
                rowsAndCols += 1
                Swap(rowPivots(pivot), rowPivots(bestRow))
            End If

            ' ----- Swap column pivot values for the best column.
            If (colPivots(pivot) <> colPivots(bestCol)) Then
                rowsAndCols += 1
                Swap(colPivots(pivot), colPivots(bestCol))
            End If

            ' ----- Work with the current pivot points.
            rowToPivot = rowPivots(pivot)
            colToPivot = colPivots(pivot)

            ' ----- Modify the remaining rows from the pivot points.
            For eachRow = (pivot + 1) To rank
                rowIndex = rowPivots(eachRow)
                destMatrix(rowIndex, colToPivot) = _
                    -destMatrix(rowIndex, colToPivot) / _
                    destMatrix(rowToPivot, colToPivot)
                For eachCol = (pivot + 1) To rank
                    colIndex = colPivots(eachCol)
                    destMatrix(rowIndex, colIndex) += _
                        destMatrix(rowIndex, colToPivot) * _
                        destMatrix(rowToPivot, colIndex)
                Next eachCol
            Next eachRow
        Next pivot

        ' ----- Detect a non-invertible matrix.
        If (destMatrix(rowPivots(rank), colPivots(rank)) = 0) Then
            Throw New Exception("Non-invertible matrix used for LU.")
        ElseIf (Math.Abs(destMatrix(rowPivots(rank), colPivots(rank))) / _
                rowNorm(rowPivots(rank))) < (Deps * oldMax) Then
            'Throw New Exception("Non-invertible matrix used for LU.")
        End If

        ' ----- Success. Return the LU triangular matrix.
        Return destMatrix
    End Function